package com.lily.aidouzixun.threadpool;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * Handle the RejectedTask when the sensitive of the pool is tight.
 * The handler wrapper the Default RejectedExecutionHandler, but add a new
 * solution rather apply the Four Alternative Solutions.
 * Put the task into a infinity blocking queue to make sure
 * no task would be abort.
 *
 * All the delayed task would be detected when a thread ends a task and
 * added to the working queue.
 */
public class RejectedTaskHandler implements RejectedExecutionHandler {

    // LifeGuard is the alternative queue
    private LinkedBlockingQueue<Runnable> lifeGuard;
    private ReentrantLock lifeGuardLock;

    public RejectedTaskHandler() {
        lifeGuard = new LinkedBlockingQueue<>();
        lifeGuardLock = new ReentrantLock();
    }


    public boolean isLifeGuardEmpty() {
        return lifeGuard.isEmpty();
    }

    public Runnable getTaskFromLifeGuard() {
        Runnable r;
        try {
            lifeGuardLock.lock();
            r = lifeGuard.take();
            return r;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lifeGuardLock.unlock();
        }
        return null;
    }

    public int getQueueSize() {
        return lifeGuard.size();
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        try {
            lifeGuardLock.lock();
            lifeGuard.put(r);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lifeGuardLock.unlock();
        }
    }
}

